﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.Linq;
using System.Net.Http;
using System.Security.Cryptography;
using System.Security.Policy;
using System.Threading;
using System.Threading.Tasks;
using Common;
using Common.Config;
using Common.Model;
using ConsoleService.API;
using ConsoleService.Cache;
using ConsoleService.EventBus;
using ConsoleService.Helps;
using ConsoleService.Model;
using ConsoleService.Services;
using CSRedis;
using HtmlAgilityPack;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Caching.Redis;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting.Internal;
using Microsoft.Extensions.Logging;
using NETCore.MailKit.Extensions;
using NETCore.MailKit.Infrastructure.Internal;
using Newtonsoft.Json;
using NLog;
using NLog.Web;
using Quartz;
using Quartz.Impl;
using StackExchange.Redis;
using static System.Net.Mime.MediaTypeNames;
using static ConsoleService.Model.gupiao;

namespace ConsoleService
{
    public class Program
    {
        //用来阻止程序退出
        private static readonly ManualResetEvent _shutdownBlock = new ManualResetEvent(false);
        private static Logger logger = LogManager.GetCurrentClassLogger();
        //private 防止外面访问， static 唯一只有一个 readonly 避免地址被修改 引用失效影响锁
        private static readonly object LOCK = new object();
        static void Main(string[] args)
        {

            var builder = new ConfigurationBuilder();
            builder.AddJsonFile("appsettings.json");
            var configuration = builder.Build();

            //获取配置信息
            Configs.RabbitHostName = configuration.GetSection("RabbitMQ:HostName").Value;
            Configs.RabbitUserName = configuration.GetSection("RabbitMQ:UserName").Value;
            Configs.RabbitPassWord = configuration.GetSection("RabbitMQ:Password").Value;
            Configs.RabbitVirtualHost = configuration.GetSection("RabbitMQ:RabbitVirtualHost").Value;
            Configs.WebUrl = configuration.GetSection("WebUrl").Value;

            IServiceCollection services = new ServiceCollection();
            services.AddOptions();
            services.AddLogging();

            //发邮件
            services.Configure<EmailOptions>(configuration.GetSection("EmailOptions"));
            services.AddMailKit(optionBuilder =>
            {
                optionBuilder.UseMailKit(new MailKitOptions()
                {
                    //get options from sercets.json
                    Server = configuration.GetSection("EmailOptions:Host").Value,
                    Port = Convert.ToInt32(configuration.GetSection("EmailOptions:Port").Value),
                    SenderName = configuration.GetSection("EmailOptions:SenderName").Value,
                    SenderEmail = configuration.GetSection("EmailOptions:FromAddress").Value,

                    // can be optional with no authentication 
                    Account = configuration.GetSection("EmailOptions:UserName").Value,
                    Password = configuration.GetSection("EmailOptions:Password").Value,
                    // enable ssl or tls
                    Security = true
                });
            });

            //注册任务调度
            services.AddSingleton<ISchedulerFactory, StdSchedulerFactory>();//注册ISchedulerFactory的实例。
            services.AddSingleton<MQService, MQService>();
            services.AddSingleton<EmailServices, EmailServices>();
            services.AddSingleton<JobServices, JobServices>();
            services.AddSingleton<EventBusServices, EventBusServices>();



            //注册自redis缓存服务
            services.AddSingleton(typeof(ICacheService), new CSRRedisCacheService(configuration.GetSection("Cache:ConnectionString").Value));

            services.AddHttpClient();
            IServiceProvider serviceProvider = services.BuildServiceProvider();
            NLogBuilder.ConfigureNLog("nlog.config");
            RunService(serviceProvider);

            //阻止程序退出
            Console.CancelKeyPress += Console_CancelKeyPress;
            AppDomain.CurrentDomain.ProcessExit += (sender, eventArgs) =>
            {
                //等待退出信号触发
                _shutdownBlock.WaitOne();
            };
        }

        private static void RunService(IServiceProvider serviceProvider)
        {
            var MQ_Service = serviceProvider.GetService<MQService>();
            var Job_Service = serviceProvider.GetService<JobServices>();
            var cache = serviceProvider.GetService<ICacheService>();
            var Email_Services = serviceProvider.GetService<EmailServices>();
            //var bus = serviceProvider.GetService<EventBusServices>();
            ////订阅
            //bus.Subscribe<OrderCreatedEvent, OrderCreatedEventHandler>();
            //var order = new OrderCreatedEvent() { OrderId = 1, OrderName = DateTime.Now.ToString("yyyy-MM-dd"), OccurredOn = "123" };
            ////发布消息
            //bus.Publish(order);

            //读取消息队列
            Thread t = new Thread(x =>
            {
                MQ_Service.Run();
            });
            t.Start();


            //读取任务调度
            //Thread t1 = new Thread(x =>
            //{
            //    _ = Job_Service.Run();
            //});
            //t1.Start();



            //读取redis订阅
            Thread t3 = new Thread(x =>
            {
                //cache.GetRedis().Subscribe(
                //  ("chan1", msg =>
                //  {
                //      string text = $"频道：{msg.Channel}，内容：{msg.Body}，时间：{DateTime.Now.ToString()}";
                //      Console.WriteLine(text);
                //      //Test(cache.GetRedis());
                //  }
                //));

                //cache.GetRedis().Subscribe(
                // ("chan2", msg =>
                // {
                //     string text = $"频道：{msg.Channel}，内容：{msg.Body}，时间：{DateTime.Now.ToString()}";
                //     Console.WriteLine(text);
                //     //TestRequest();
                // }
                //));

                cache.GetRedis().Subscribe(
                ("GetOil", msg =>
                {

                    var count = cache.GetRedis().Get<int>("GetOilCount");

                    if (count < 5)
                    {
                        CommonAPI commonAPI = new CommonAPI();
                        var result = commonAPI.GetOilPrice3("");
                        string text = $"频道：{msg.Channel}，内容：{msg.Body}，时间：{DateTime.Now.ToString()}，同步数据：{(result ? "成功" : "失败")}";
                        logger.Warn(text);
                        if (!result)
                        {
                            Thread.Sleep(5000);
                            cache.GetRedis().Publish("GetOil", $"自动重试{count}");
                            cache.GetRedis().Set("GetOilCount", count += 1);
                        }
                        Console.WriteLine(text);
                    }
                    else
                    {
                        cache.GetRedis().Set("GetOilCount", 0);
                        Console.WriteLine("停止重试！");
                    }
                }
                ));

                // cache.GetRedis().Subscribe(
                // ("update_company", msg =>
                // {
                //     string text = $"频道：{msg.Channel}，内容：{msg.Body}，时间：{DateTime.Now.ToString()}";
                //     Console.WriteLine(text);
                //     logger.Warn(text);
                //     Test2(cache.GetRedis());
                // }
                // ));

                // cache.GetRedis().Subscribe(
                //("update_company2", msg =>
                //{
                //    string text = $"频道：{msg.Channel}，内容：{msg.Body}，时间：{DateTime.Now.ToString()}";
                //    Console.WriteLine(text);
                //    logger.Warn(text);
                //    Test4();
                //}
                // ));


                cache.GetRedis().Subscribe(
              ("testEmail", msg =>
              {
                  string text = $"频道：{msg.Channel}，内容：{msg.Body}，时间：{DateTime.Now.ToString()}";
                  Console.WriteLine(text);
                  logger.Warn(text);

                  Console.WriteLine("开始发送邮件...");

                  EmailModel model = new EmailModel();
                  model.Subject = "这是邮件主题";
                  model.Context = @"一半烟火以谋生，一半诗意以谋爱。
                  落日沉溺于橘色的海，晚风沦陷于赤诚的爱。
                  我本无意惊鸿，奈何惊鸿入我心。
                  市井长巷，聚拢来是烟火，摊开是人间。
                  倘若南风知我意，莫将晚霞落黄昏。
                  且行且忘且随风，且行且看且从容。
                  少年没有乌托邦，心有远方自明朗。
                  夜色难免黑凉，前行必有曙光。
                  认识自己，是寻找还没有认识的自己。
                  慢慢来，好戏都在烟火里！[保卫萝卜_哇]​";
                  model.To = new List<string>() { "1294833881@qq.com" };
                  model.Cc = new List<string>() { "2653859300@qq.com" };
                  model.IsHtml = true;

                  RabbitMQUtil.SendMessage(model.ToJson(), "emailQueue");
              }
                ));
            });
            t3.Start();
        }

        public static void getCompany()
        {
            while (true)
            {
                var url = $"https://stock.xueqiu.com/v5/stock/realtime/quotec.json?symbol=SH000001,SZ399001,SZ399006";

                var result = WebHelper.HttpRequest(url);

                var data = JsonConvert.DeserializeObject<Root>(result);

                Console.WriteLine($"---------------------------------------");

                data.data.ForEach(c =>
                {
                    Console.WriteLine($"代码：{c.symbol},{c.current},{c.percent}");
                });

                Thread.Sleep(1500);
            }
        }


        public static void Test4()
        {
            CommonAPI commonAPI = new CommonAPI();
            var pageindex = 1;
            var pageSize = 1000;//分页条数
            var result2 = commonAPI.GetCompanyList2(pageindex, pageSize);
            var records = result2.data.records;//总记录数
            var total = records % pageSize == 0 ? records / pageSize : records / pageSize + 1;//总页数
            var text = $"开始分页更新公司数据共计：{records}条数据，总页数：{total}....";

            Console.WriteLine(text);
            logger.Warn(text);


            for (int i = pageindex; i <= total; i++)
            {
                Console.WriteLine($"-----------当前第{i}页：-------------");
                var result = commonAPI.GetCompanyList2(i, pageSize);

                var New_pageSize = 100;//分页条数
                int j = New_pageSize;
                for (int z = 0; z < result.data.rows.Count(); z += New_pageSize)
                {
                    var list = result.data.rows.Take(j).Skip(z).ToList();

                    j += New_pageSize;
                }
            }

        }

        public static void Test2(CSRedisClient redis)
        {
            CommonAPI commonAPI = new CommonAPI();
            Stopwatch s = new Stopwatch();
            s.Start();
            Console.WriteLine("开始解析数据.....");
            logger.Warn("开始解析数据.....");

            var currentList = commonAPI.GetCompanyList();

            redis.HSet("CompanyList", "name", currentList.Select(x => x.name).ToJson());

            var Alllist = currentList.Select(x => x.name).ToList();

            Console.WriteLine($"获取数据共计：${Alllist.Count}");

            var pageSize = 50;//分页条数
            int j = pageSize;
            for (int i = 0; i < Alllist.Count(); i += pageSize)
            {
                Console.WriteLine($"第{i}页：");
                var list = Alllist.Take(j).Skip(i).ToList();
                Console.WriteLine("数量:" + list.Count());
                commonAPI.GetSearchCompany(list, false);
                Thread.Sleep(10000);
                j += pageSize;
            }
            s.Stop();
            var msg = $"同步公司数据成功用时：{s.Elapsed.ToString()}" + DateTime.Now.ToString();

            logger.Warn(msg);
            Console.WriteLine(msg);
        }




        public static void Update(List<Company> list)
        {
            var result = new List<Company>();
            var commonAPI = new CommonAPI();
            var index = 1;
            foreach (var item in list)
            {
                var url = $"https://www.tianyancha.com/company/{item.tianyancha_Id}";
                var text = $"{index}.{item.name}-{url}";
                Console.WriteLine(text);
                logger.Warn(text);
                var entity = commonAPI.GetCompanyDetail(url);
                if (entity != null)
                {
                    result.Add(entity);
                }
                index++;
            }
            commonAPI.UpdateCompany(result);
        }

        private static void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e)
        {
            e.Cancel = true;
            _shutdownBlock.Set();
        }


    }
}
